package com.web.document.service.impl;

import com.web.common.basic.api.BasicSysDictApi;
import com.web.common.basic.api.ElasticsearchApi;
import com.web.common.basic.elasticsearch.entity.ElasticDocResponse;
import com.web.common.basic.elasticsearch.entity.ElasticParam;
import com.web.common.basic.entity.ElasticsearchIndex;
import com.web.common.datasource.DataSourcesSymbol;
import com.web.common.document.entity.DocumentChapter;
import com.web.common.document.entity.DocumentChapterEntity;
import com.web.common.document.entity.DocumentContent;
import com.web.common.document.entity.DocumentContentEntity;
import com.web.common.document.entity.DocumentInfo;
import com.web.common.document.entity.DocumentInfoEntity;
import com.web.common.document.entity.DocumentInfoShareUser;
import com.web.common.document.entity.ShareDocChapter;
import com.web.common.document.entity.ShareDocInfo;
import com.web.common.result.R;
import com.web.common.result.ResultEnum;
import com.web.common.security.FeignInnerEntity;
import com.web.common.tool.RandomString;
import com.web.common.tool.Symbols;
import com.web.common.user.api.UserApi;
import com.web.common.user.entity.WebUser;
import com.web.common.user.entity.WebUserEntity;
import com.web.document.mapper.DocumentChapterMapper;
import com.web.document.mapper.DocumentInfoMapper;
import com.web.document.mapper.DocumentInfoShareUserMapper;
import com.web.service.handler.auth.UserUtil;
import com.web.service.handler.error.CustomException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 文档信息 服务实现类
 * </p>
 *
 * @author zhouhui
 * @since 2023-12-04
 */
@Service
public class DocumentInfoServiceImpl extends ServiceImpl<DocumentInfoMapper, DocumentInfo> {
	
	/** 随机字符串的长度 */
	private static final int RANDOM_STR_LEN = 16;
	
	private static final int ROOT_TREE = 0;
	
	private ObjectMapper mapper = new ObjectMapper();
	
	@Autowired
	private ElasticsearchApi elasticsearchApi;
	
	@Autowired
	private DocumentInfoMapper documentInfoMapper;
	
	@Autowired
	private DocumentInfoShareUserMapper documentInfoShareUserMapper;
	
	@Autowired
	private DocumentChapterMapper documentChapterMapper;
	
	@Autowired
	private BasicSysDictApi basicSysDictApi;
	
	@Autowired
	private PlatformTransactionManager txManagerTwo;
	
	@Autowired
	private UserApi userApi;
	
	public DocumentInfoServiceImpl() {
		SimpleModule module = new SimpleModule();
		module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
		mapper.registerModule(module);
	}
	
	/**
	 * 获取文档信息列表
	 * @param condition 查询条件
	 * @return R<IPage<DocumentInfoEntity>> 分页数据列表
	 *
	 * @author zhouhui
	 * @since 2023.12.11 
	 */
	public R<IPage<DocumentInfoEntity>> getDocInfoList(DocumentInfoEntity condition) {
		WebUser user = UserUtil.getUser();
		condition.setOwnerId(user.getUserId());
		
		setSearchCondition(condition);
		Page<DocumentInfo> page = new Page<>(condition.getPage(), condition.getSize());
		IPage<DocumentInfoEntity> result = documentInfoMapper.getDocInfoList(page, condition);
		
		//获取字典项
		Map<String, String> shareType = getSysDict("doc_share_type");
		Map<String, String> shareActivity = getSysDict("doc_share_activity");
		
		List<DocumentInfoEntity> records = result.getRecords();
		for(DocumentInfoEntity item: records) {
			item.setShareTypeName(shareType.get(item.getShareType().toString()));
			item.setShareActivityName(shareActivity.get(item.getShareActivity().toString()));
		}
		return R.ok(result);
	}
	
	/**
	 * 获取文档分享人员列表
	 * @param condition
	 * @return
	 *
	 * @author zhouhui
	 * @since 2024.02.27 
	 */
	public R<DocumentInfoEntity> getDocInfoDetail(DocumentInfoEntity condition) {
		WebUser user = UserUtil.getUser();
		condition.setOwnerId(user.getUserId());
		
		DocumentInfoEntity info = new DocumentInfoEntity();
		List<Integer> userIdList = documentInfoShareUserMapper.getUserIdListByInfo(condition);
		if(userIdList.isEmpty()) {
			info.setUserList(new ArrayList<>());
			return R.ok(info);
		}
		
		WebUserEntity searchCondition = new WebUserEntity();
		searchCondition.setUserIdList(userIdList);
		searchCondition.setSize(-1);
		R<List<WebUserEntity>> result = userApi.getAllUserList(searchCondition);
		if(result == null) {
			return R.fail(null, ResultEnum.FEIGN_ERROR);
		}
		if(!ResultEnum.SUCCESS.getCode().equals(result.getCode())) {
			return R.fail(null, result.getMessage());
		}
		
		info.setUserList(result.getData());
		return R.ok(info);
	}
	
	/**
	 * 获取字典信息
	 * @param type 字典类型
	 * @return Map<String, String> value-label
	 *
	 * @author zhouhui
	 * @since 2023.12.11 
	 */
	private Map<String, String> getSysDict(String type){
		List<String> typeList = new ArrayList<>(1);
		typeList.add(type);
		R<Map<String, String>> dictResult = basicSysDictApi.getDictMap(typeList);
		if(!ResultEnum.SUCCESS.getCode().equals(dictResult.getCode())) {
			throw new CustomException(ResultEnum.FEIGN_ERROR.getMessage());
		}
		return dictResult.getData();
	}
	
	
	/**
	 * 设置查询条件
	 * @param condition 查询条件
	 *
	 * @author zhouhui
	 * @since 2023.12.11 
	 */
	private void setSearchCondition(DocumentInfoEntity condition) {
		if(StringUtils.hasText(condition.getTitle())) {
			condition.setTitle("%" + condition.getTitle() + "%");
		}
	}

	/**
	 * 保存文档的基本信息。
	 * @param info 文档基本信息
	 * @return R<Object>处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.08 
	 */
	public R<Object> saveDocInfo(DocumentInfoEntity info) {
		verifyDocumentInfoParam(info);
		
		WebUser user = UserUtil.getUser();
		info.setShareCode(RandomString.getText(RANDOM_STR_LEN));
		info.setOwnerId(user.getUserId());
		info.setDelFlag(DataSourcesSymbol.DEL_FLAG_VALUE_0);
		info.setCreateTime(LocalDateTime.now());
		
		DocumentInfo saveData = new DocumentInfo();
		BeanUtils.copyProperties(info, saveData);
		saveData.setMainId(null);
		
		DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
		TransactionStatus status = txManagerTwo.getTransaction(definition);
		try {
			documentInfoMapper.insert(saveData);
			
			if(info.getShareType() == 2 && !info.getUserIdList().isEmpty()) {
				//保存指定人员
				saveShareUserList(info, saveData.getMainId());
			}
			txManagerTwo.commit(status);
		} catch (Exception e) {
			e.printStackTrace();
			txManagerTwo.rollback(status);
		}
		
		return R.ok(saveData);
	}
	
	/**
	 * 校验文档信息
	 * @param info文档信息
	 *
	 * @author zhouhui
	 * @since 2023.12.08 
	 */
	private void verifyDocumentInfoParam(DocumentInfoEntity info) {
		if(info.getShareType() == 2 && (info.getUserIdList() == null || info.getUserIdList().isEmpty())) {
			throw new CustomException("未指定分享用户");
		}
		if(info.getShareActivity() == 2 && info.getExpirationDate() == null) {
			throw new CustomException("未设置分享到期时间");
		}
		if(info.getShareActivity() == 2 && info.getExpirationDate().isBefore(LocalDateTime.now())) {
			throw new CustomException("分享到期时间不能小于当前时间");
		}
		
		//处理数据
		if(info.getShareActivity() == 1) {
			info.setExpirationDate(LocalDateTime.parse("9999-12-31T00:00:00"));
		}else if(info.getShareActivity() == 0) {
			info.setExpirationDate(null);
		}
		if(info.getShareType() == 0) {
			info.setShareActivity(0);
			info.setExpirationDate(null);
		}
	}
	
	/**
	 * 保存分享给用户的列表
	 * @param info 文档信息
	 * @param infoId 文档信息Id
	 *
	 * @author zhouhui
	 * @since 2023.12.11
	 */
	private void saveShareUserList(DocumentInfoEntity info, Integer infoId) {
		List<DocumentInfoShareUser> shareList = new ArrayList<>();
		for (int i = 0; i < info.getUserIdList().size(); i++) {
			DocumentInfoShareUser item = new DocumentInfoShareUser();
			item.setUserId(info.getUserIdList().get(i));
			item.setInfoId(infoId);
			item.setCreateTime(LocalDateTime.now());
			shareList.add(item);
		}
		documentInfoShareUserMapper.batchSave(shareList);
	}
	
	/**
	 * 更新文档信息
	 * @param info 文档信息
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.11 
	 */
	public R<Object> updateDocInfo(DocumentInfoEntity info) {
		verifyDocumentInfoParam(info);
		
		WebUser user = UserUtil.getUser();
		
		DocumentInfo doc = new DocumentInfo();
		BeanUtils.copyProperties(info, doc);
		doc.setUpdateTime(LocalDateTime.now());
		doc.setShareCode(null);
		
		DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
		TransactionStatus status = txManagerTwo.getTransaction(definition);
		try {
			LambdaUpdateWrapper<DocumentInfo> docUpdate = new LambdaUpdateWrapper<>();
			docUpdate.eq(DocumentInfo::getMainId, info.getMainId());
			docUpdate.eq(DocumentInfo::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
			docUpdate.eq(DocumentInfo::getOwnerId, user.getUserId());
			docUpdate.set(DocumentInfo::getExpirationDate, info.getExpirationDate());
			int updateRow = documentInfoMapper.update(doc, docUpdate);
			if(updateRow != 1) {
				throw new CustomException("文档信息更新失败");
			}
			LambdaQueryWrapper<DocumentInfoShareUser> del = new LambdaQueryWrapper<>();
			del.eq(DocumentInfoShareUser::getInfoId, info.getMainId());
			documentInfoShareUserMapper.delete(del);
			
			if(info.getShareType() == 2 && !info.getUserIdList().isEmpty()) {
				//保存指定人员
				saveShareUserList(info, info.getMainId());
			}
			txManagerTwo.commit(status);
		} catch (Exception e) {
			e.printStackTrace();
			txManagerTwo.rollback(status);
		}
		
		return R.ok();
	}
	
	/**
	 * 删除文档信息。
	 * 注：文档信息标记删除，关联信息继续保存！！
	 * @param info 需要删除的文档信息
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.12 
	 */
	public R<Object> deleteDocInfo(DocumentInfoEntity info){
		WebUser user = UserUtil.getUser();
		
		LambdaUpdateWrapper<DocumentInfo> updateInfo = new LambdaUpdateWrapper<>();
		updateInfo.eq(DocumentInfo::getMainId, info.getMainId());
		updateInfo.eq(DocumentInfo::getOwnerId, user.getUserId());
		updateInfo.eq(DocumentInfo::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		updateInfo.set(DocumentInfo::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_1);
		updateInfo.set(DocumentInfo::getUpdateTime, LocalDateTime.now());
		int deleteRow = documentInfoMapper.update(null, updateInfo);
		if(deleteRow != 1) {
			return R.fail(null, ResultEnum.DATA_DELETE_ERROR);
		}
		return R.ok();
	}
	
	/**
	 * 保存文档的章节信息。
	 * 1、判断文档信息是否存在；
	 * 2、校验父级章节是否存在。
	 * @param chapter 章节信息
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.12 
	 */
	public R<Object> saveChapter(DocumentChapterEntity chapter){
		WebUser user = UserUtil.getUser();
		
		LambdaQueryWrapper<DocumentInfo> infoQuery = new LambdaQueryWrapper<>();
		infoQuery.eq(DocumentInfo::getMainId, chapter.getInfoId());
		infoQuery.eq(DocumentInfo::getOwnerId, user.getUserId());
		infoQuery.eq(DocumentInfo::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		DocumentInfo info = documentInfoMapper.selectOne(infoQuery);
		if(info == null) {
			throw new CustomException("未查询到文档信息");
		}
		//校验父节点是否存在
		if(chapter.getParentId().intValue() > 0) {
			DocumentChapter parentChapter = checkChapterByUser(user.getUserId(), chapter.getParentId());
			if(parentChapter.getType().intValue() == 1) {
				throw new CustomException("父节点不能为章节内容");
			}
		}else {
			chapter.setParentId(0);
		}
		DocumentChapter saveChapter = new DocumentChapter();
		BeanUtils.copyProperties(chapter, saveChapter);
		saveChapter.setMainId(null);
		saveChapter.setOwnerId(user.getUserId());
		saveChapter.setCreateTime(LocalDateTime.now());
		saveChapter.setDelFlag(DataSourcesSymbol.DEL_FLAG_VALUE_0);
		documentChapterMapper.insert(saveChapter);
		
		return R.ok(chapter);
	}
	
	/**
	 * 删除章节信息
	 * @param chapter 章节信息
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.17
	 */
	public R<Object> deleteChapter(DocumentChapterEntity chapter){
		WebUser user = UserUtil.getUser();
		
		//判断登录用户是否有操作权限
		checkChapterByUser(user.getUserId(), chapter.getMainId());
		
		LambdaUpdateWrapper<DocumentChapter> deleteChapter = new LambdaUpdateWrapper<>();
		deleteChapter.eq(DocumentChapter::getMainId, chapter.getMainId());
		deleteChapter.set(DocumentChapter::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_1);
		deleteChapter.set(DocumentChapter::getUpdateTime, LocalDateTime.now());
		documentChapterMapper.update(null, deleteChapter);
		return R.ok();
	}
	
	/**
	 * 更新章节信息。
	 * 注：只是调整章节的标题。
	 * @param chapter 章节信息
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.17
	 */
	public R<Object> updateChapter(DocumentChapterEntity chapter){
		WebUser user = UserUtil.getUser();
		
		//判断登录用户是否有操作权限
		checkChapterByUser(user.getUserId(), chapter.getMainId());
		
		LambdaUpdateWrapper<DocumentChapter> updateChapter = new LambdaUpdateWrapper<>();
		updateChapter.eq(DocumentChapter::getMainId, chapter.getMainId());
		updateChapter.eq(DocumentChapter::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		updateChapter.set(DocumentChapter::getTitle, chapter.getTitle());
		updateChapter.set(DocumentChapter::getUpdateTime, LocalDateTime.now());
		updateChapter.set(DocumentChapter::getSort, chapter.getSort());
		documentChapterMapper.update(null, updateChapter);
		return R.ok();
	}
	
	/**
	 * 校验用户有没有操作章节的权限
	 * @param userId 用户的Id
	 * @param chapterId 章节的Id
	 *
	 * @author zhouhui
	 * @since 2023.12.17
	 */
	private DocumentChapter checkChapterByUser(Integer userId, Integer chapterId) {
		LambdaQueryWrapper<DocumentChapter> chapterQuery = new LambdaQueryWrapper<>();
		chapterQuery.eq(DocumentChapter::getMainId, chapterId);
		chapterQuery.eq(DocumentChapter::getOwnerId, userId);
		chapterQuery.eq(DocumentChapter::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		DocumentChapter chapter = documentChapterMapper.selectOne(chapterQuery);
		if(chapter == null) {
			throw new CustomException("没有查询到对应的章节信息");
		}
		return chapter;
	}
	
	/**
	 * 保存/更新文档内容
	 * @param content 文档内容
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.14
	 */
	public R<Object> saveContent(DocumentContentEntity content){
		WebUser user = UserUtil.getUser();
		
		//判断登录用户是否有操作权限
		DocumentChapter chapter = checkChapterByUser(user.getUserId(), content.getChapterId());
		if(chapter.getType().intValue() == 0) {
			throw new CustomException("文档目录不能设置章节内容");
		}
		
		if(StringUtils.hasText(chapter.getContentIndex())) {
			//章节和文档已存在关联关系
			if(chapter.getContentIndex().equals(content.getDocumentId())) {
				throw new CustomException("上传的文档索引和已存在的不一致");
			}
			//只更新文档内容
			DocumentContent docContent = new DocumentContent();
			docContent.setDocumentId(chapter.getContentIndex());
			docContent.setContent(content.getContent());
			docContent.setInfoId(chapter.getInfoId());
			docContent.setUpdateTime(LocalDateTime.now());
			docContent.setContentText(content.getContentText());
			updateContent(docContent);
		}else {
			//新增章节和文档的关联关系
			DocumentContent docContent = new DocumentContent();
			docContent.setOwner(user.getUserId());
			docContent.setCreateTime(LocalDateTime.now());
			String contentIndex = UUID.randomUUID().toString();
			docContent.setDocumentId(contentIndex);
			docContent.setContent(content.getContent());
			docContent.setInfoId(chapter.getInfoId());
			docContent.setUpdateTime(LocalDateTime.now());
			docContent.setContentText(content.getContentText());
			
			//保存文档内容
			saveDocContent(docContent);
			
			//保存文档章节与内容的关联关系
			LambdaUpdateWrapper<DocumentChapter> updateChapter = new LambdaUpdateWrapper<>();
			updateChapter.eq(DocumentChapter::getMainId, content.getChapterId());
			updateChapter.set(DocumentChapter::getContentIndex, contentIndex);
			updateChapter.set(DocumentChapter::getUpdateTime, LocalDateTime.now());
			documentChapterMapper.update(null, updateChapter);
		}
		return R.ok();
	}
	
	/**
	 * 保存文档内容
	 * @param content 文档内容
	 *
	 * @author zhouhui
	 * @since 2023.12.14
	 */
	private void saveDocContent(DocumentContent content) {
		ElasticParam param = new ElasticParam();
		param.setEndpoint(Symbols.FORWARD_SLASH + ElasticsearchIndex.DOCUMENT_INDEX + "/_doc/" + content.getDocumentId());
		param.setMethod(HttpMethod.POST.name());
		
		String body = null;
		try {
			JavaTimeModule module = new JavaTimeModule();
			module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_DATE_TIME));
			mapper.registerModule(module);
			
			body = mapper.writeValueAsString(content);
		} catch (Exception e) {
			e.printStackTrace();
		}
		param.setJsonEntity(body);
		R<Object> result = elasticsearchApi.customOperate(param, FeignInnerEntity.HTTP_INNER_VALUE);
		if(!ResultEnum.SUCCESS.getCode().equals(result.getCode())) {
			throw new CustomException(result.getMessage());
		}
	}
	
	/**
	 * 更新文档信息
	 * @param content 文档信息
	 *
	 * @author zhouhui
	 * @since 2023.12.18 
	 */
	private void updateContent(DocumentContent content) {
		ElasticParam param = new ElasticParam();
		param.setEndpoint(Symbols.FORWARD_SLASH + ElasticsearchIndex.DOCUMENT_INDEX + "/_update/" + content.getDocumentId());
		param.setMethod(HttpMethod.POST.name());
		
		Map<String, Object> map = new HashMap<>();
		map.put("detect_noop", false);
		Map<String, Object> doc = new HashMap<>();
		map.put("doc", doc);
		doc.put("content", content.getContent());
		doc.put("infoId", content.getInfoId());
		doc.put("updateTime", LocalDateTime.now());
		doc.put("contentText", content.getContentText());
		
		String body = null;
		try {
			JavaTimeModule module = new JavaTimeModule();
			module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_DATE_TIME));
			mapper.registerModule(module);
			
			body = mapper.writeValueAsString(map);
		} catch (Exception e) {
			e.printStackTrace();
		}
		param.setJsonEntity(body);
		R<Object> result = elasticsearchApi.customOperate(param, FeignInnerEntity.HTTP_INNER_VALUE);
		if(!ResultEnum.SUCCESS.getCode().equals(result.getCode())) {
			throw new CustomException(result.getMessage());
		}
	}
	
	/**
	 * 自动取消到期的分享内容
	 * @return R<Object> 处理结果
	 *
	 * @author zhouhui
	 * @since 2023.12.26 
	 */
	public R<Object> autoCancelShare(){
		LambdaUpdateWrapper<DocumentInfo> update = new LambdaUpdateWrapper<>();
		update.in(DocumentInfo::getShareType, 1,2);
		update.eq(DocumentInfo::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		update.eq(DocumentInfo::getShareActivity, 2);
		update.le(DocumentInfo::getExpirationDate, LocalDateTime.now());
		update.set(DocumentInfo::getShareActivity, 0);
		update.set(DocumentInfo::getExpirationDate, null);
		update.set(DocumentInfo::getUpdateTime, LocalDateTime.now());
		documentInfoMapper.update(null, update);
		return R.ok();
	}
	
	/**
	 * 将列表构建成树形结构
	 * @param chapterList 章节列表
	 * @return List<ShareDocChapter> 树形列表
	 *
	 * @author zhouhui
	 * @since 2023.12.19 
	 */
	public List<ShareDocChapter> buildTree(List<ShareDocChapter> chapterList){
		List<ShareDocChapter> tree = new ArrayList<>(chapterList.size());
		Map<Integer, ShareDocChapter> treeMap = new HashMap<>();
		for(ShareDocChapter item: chapterList) {
			treeMap.put(item.getMainId(), item);
			
			if(item.getParentId().intValue() == ROOT_TREE) {
				item.setTreeIndex(item.getMainId() + "");
				tree.add(item);
			}else {
				ShareDocChapter chapterItem = treeMap.get(item.getParentId());
				if(chapterItem == null) {
					continue;
				}
				String prefix = chapterItem.getTreeIndex() + "-";
				
				if(chapterItem.getChildren() == null) {
					chapterItem.setChildren(new ArrayList<>());
				}
				item.setTreeIndex(prefix + item.getMainId());
				chapterItem.getChildren().add(item);
			}
		}
		return tree;
	}
	
	/**
	 * 根据文档Id获取章节列表
	 * @param chapter 文档Id
	 * @return R<ShareDocInfo> 章节信息列表
	 *
	 * @author zhouhui
	 * @since 2024.01.14
	 */
	public R<ShareDocInfo> getChapterList(DocumentChapterEntity chapter) {
		WebUser user = UserUtil.getUser();
		LambdaQueryWrapper<DocumentInfo> infoQuery = new LambdaQueryWrapper<>();
		infoQuery.eq(DocumentInfo::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		infoQuery.eq(DocumentInfo::getMainId, chapter.getInfoId());
		infoQuery.eq(DocumentInfo::getOwnerId, user.getUserId());
		DocumentInfo info = documentInfoMapper.selectOne(infoQuery);
		if(info == null) {
			throw new CustomException("未查询到文档信息");
		}
		List<ShareDocChapter> chapterList = documentChapterMapper.getChapterList(info.getMainId());
		List<ShareDocChapter> treeList = buildTree(chapterList);
		
		ShareDocInfo shareDocInfo = new ShareDocInfo();
		shareDocInfo.setTitle(info.getTitle());
		shareDocInfo.setShareCode(info.getShareCode());
		shareDocInfo.setChapterList(treeList);
		return R.ok(shareDocInfo);
	}
	
	/**
	 * 获取文档内容
	 * @param content 章节Id
	 * @return R<DocumentContent> 文档内容
	 *
	 * @author zhouhui
	 * @since 2024.01.14
	 */
	public R<DocumentContent> getDocumentConent(DocumentContentEntity content) {
		WebUser user = UserUtil.getUser();
		LambdaQueryWrapper<DocumentChapter> chapterQuery = new LambdaQueryWrapper<>();
		chapterQuery.eq(DocumentChapter::getDelFlag, DataSourcesSymbol.DEL_FLAG_VALUE_0);
		chapterQuery.eq(DocumentChapter::getOwnerId, user.getUserId());
		chapterQuery.eq(DocumentChapter::getMainId, content.getChapterId());
		DocumentChapter chapter = documentChapterMapper.selectOne(chapterQuery);
		if(chapter == null) {
			throw new CustomException("未查询到文档内容");
		}
		if(chapter.getType().equals(0)) {
			throw new CustomException("章节类型为目录，无文档内容");
		}else {
			if(!StringUtils.hasText(chapter.getContentIndex())) {
				return R.ok();
			}
		}
		return R.ok(getContentByIndex(chapter.getContentIndex()));
	}
	
	/**
	 * 根据文档内容的索引查询文档内容
	 * @param index 索引值
	 * @return 文档内容
	 *
	 * @author zhouhui
	 * @since 2024.01.14
	 */
	public DocumentContent getContentByIndex(String index) {
		ElasticParam param = new ElasticParam();
		param.setEndpoint(Symbols.FORWARD_SLASH + ElasticsearchIndex.DOCUMENT_INDEX + "/_doc/" + index);
		param.setMethod(HttpMethod.GET.name());
		R<Object> result = elasticsearchApi.customOperate(param, FeignInnerEntity.HTTP_INNER_VALUE);
		if(!ResultEnum.SUCCESS.getCode().equals(result.getCode())) {
			throw new CustomException(result.getMessage());
		}
		if(result.getData() == null || !StringUtils.hasText(result.getData().toString())) {
			throw new CustomException(ResultEnum.DATA_QUERY_NO_RESULT.getMessage());
		}
		ElasticDocResponse<DocumentContent> res = null;
		try {
			res = mapper.readValue(result.getData().toString(), new TypeReference<ElasticDocResponse<DocumentContent>>() {});
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		if(res == null) {
			throw new CustomException(ResultEnum.JSON_ERROR.getMessage());
		}
		if(!res.getFound().booleanValue()) {
			throw new CustomException("未查询到文档内容信息");
		}
		return res.getSource();
	}
}
